#!/usr/bin/env python3
"""
分布式文件同步系统 - 简化TUI界面
无需外部依赖，仅使用Python标准库

运行方式:
python simple_tui.py
"""

import json
import time
import sys
import os
from datetime import datetime
from typing import Dict, Any, Optional

try:
    import urllib.request
    import urllib.error
except ImportError:
    print("❌ Python版本过低，请使用Python 3.x")
    sys.exit(1)


class SimpleTUI:
    """简化的TUI界面，无外部依赖"""

    def __init__(self, backend_host: str = "localhost", backend_port: int = 8889):
        self.backend_url = f"http://{backend_host}:{backend_port}"
        self.last_update = None
        self.error_count = 0
        self.auth_token = None

        # 缓存数据
        self.cached_data = {"status": {}, "config": {}, "network": {}, "files": {}}

    def clear_screen(self):
        """清屏"""
        os.system("cls" if os.name == "nt" else "clear")

    def fetch_data(self, endpoint: str) -> Optional[Dict[str, Any]]:
        """从后端API获取数据"""
        try:
            url = f"{self.backend_url}/api/{endpoint}"
            request = urllib.request.Request(url)

            # 添加认证头 (直接使用API密钥)
            if self.auth_token:
                request.add_header("Authorization", self.auth_token)

            with urllib.request.urlopen(request, timeout=5) as response:
                if response.status == 200:
                    self.error_count = 0
                    content = response.read()
                    try:
                        text = content.decode("utf-8")
                    except UnicodeDecodeError:
                        text = content.decode("gbk", errors="ignore")

                    data = json.loads(text)
                    # 如果返回认证错误，尝试重新认证
                    if data.get("error") and "认证失败" in data.get("message", ""):
                        if self.try_auto_auth():
                            # 重新认证成功，再次尝试请求
                            request = urllib.request.Request(url)
                            request.add_header("Authorization", self.auth_token)
                            with urllib.request.urlopen(
                                request, timeout=5
                            ) as retry_response:
                                if retry_response.status == 200:
                                    retry_content = retry_response.read()
                                    try:
                                        retry_text = retry_content.decode("utf-8")
                                    except UnicodeDecodeError:
                                        retry_text = retry_content.decode(
                                            "gbk", errors="ignore"
                                        )
                                    return json.loads(retry_text)

                    return data
                else:
                    self.error_count += 1
                    return None
        except Exception as e:
            self.error_count += 1
            if self.error_count <= 3:
                print(f"❌ API请求失败: {e}")
            return None

    def login(self, username: str = "admin", password: str = "admin123") -> bool:
        """登录并获取认证令牌"""
        try:
            login_data = {"username": username, "password": password}
            data = json.dumps(login_data).encode("utf-8")

            request = urllib.request.Request(
                f"{self.backend_url}/api/login",
                data=data,
                headers={"Content-Type": "application/json"},
            )

            with urllib.request.urlopen(request, timeout=5) as response:
                if response.status == 200:
                    # 尝试不同的编码方式
                    content = response.read()
                    try:
                        text = content.decode("utf-8")
                    except UnicodeDecodeError:
                        text = content.decode("gbk", errors="ignore")

                    result = json.loads(text)
                    if result.get("success", False):
                        self.auth_token = result.get("token")
                        return True
            return False
        except Exception as e:
            print(f"登录错误: {e}")
            return False

    def get_api_key_from_logs(self) -> Optional[str]:
        """从后端日志文件中获取API密钥"""
        # 首先尝试从配置文件读取
        try:
            if os.path.exists("tui_config.json"):
                with open("tui_config.json", "r", encoding="utf-8") as f:
                    config = json.load(f)
                    api_key = config.get("api_key")
                    if api_key and len(api_key) > 20:
                        return api_key
        except Exception:
            pass

        # 从日志文件获取API密钥
        log_files = ["logs/system.log", "target/backend.log", "system.log"]

        for log_file in log_files:
            try:
                if os.path.exists(log_file):
                    with open(log_file, "r", encoding="utf-8", errors="ignore") as f:
                        # 读取最后几行，查找API密钥
                        lines = f.readlines()
                        for line in reversed(lines[-50:]):  # 检查最后50行
                            if "管理员API密钥:" in line or "API密钥:" in line:
                                # 提取密钥部分
                                parts = line.split(":")
                                if len(parts) >= 2:
                                    api_key = parts[-1].strip()
                                    if len(api_key) > 20:  # 基本验证密钥长度
                                        return api_key
            except Exception as e:
                continue
        return None

    def try_auto_auth(self) -> bool:
        """尝试自动认证：先从日志获取API密钥，失败则尝试用户名密码登录"""
        # 方法1：从日志文件获取API密钥
        api_key = self.get_api_key_from_logs()
        if api_key:
            self.auth_token = api_key
            # 测试API密钥是否有效
            test_data = self.fetch_data("status")
            if test_data and not test_data.get("error"):
                print(f"✅ 使用日志中的API密钥认证成功")
                return True
            else:
                print("⚠️ 日志中的API密钥无效，尝试用户名密码登录")

        # 方法2：尝试用户名密码登录
        if self.login():
            print("✅ 用户名密码登录成功")
            return True

        return False

    def update_cached_data(self):
        """更新缓存数据"""
        endpoints = ["status", "config", "network", "files"]
        for endpoint in endpoints:
            data = self.fetch_data(endpoint)
            if data:
                self.cached_data[endpoint] = data
        self.last_update = datetime.now()

    def print_header(self):
        """打印页头"""
        status_data = self.cached_data.get("status", {})

        # 基本信息
        node_name = status_data.get("nodeName", "Unknown")
        version = status_data.get("version", "1.0.0")
        uptime = status_data.get("uptime", 0)
        uptime_str = self.format_uptime(uptime)

        # 服务状态
        services = status_data.get("services", {})
        network_status = "运行中" if services.get("network", False) else "已停止"
        watcher_status = "运行中" if services.get("fileWatcher", False) else "已停止"
        api_status = "运行中" if services.get("api", False) else "已停止"

        print("=" * 80)
        print("🚀 分布式文件同步系统控制台")
        print("=" * 80)
        print(f"节点: {node_name} | 版本: {version} | 运行时间: {uptime_str}")
        print(
            f"网络服务: {network_status} | 文件监控: {watcher_status} | API服务: {api_status}"
        )
        print("=" * 80)

    def print_network_status(self):
        """打印网络状态"""
        print("\n🌐 网络状态:")
        print("-" * 40)

        network_data = self.cached_data.get("network", {})
        status_data = self.cached_data.get("status", {})

        # 网络信息
        network_info = status_data.get("network", {})
        port = network_info.get("port", "N/A")
        api_port = network_info.get("apiPort", "N/A")
        connections = network_info.get("connections", 0)
        max_connections = network_info.get("maxConnections", 10)

        print(f"监听端口:     {port}")
        print(f"API端口:      {api_port}")
        print(f"活动连接:     {connections}/{max_connections}")

        # 消息队列
        queues = network_data.get("messageQueues", {})
        incoming = queues.get("incoming", 0)
        outgoing = queues.get("outgoing", 0)
        print(f"传入队列:     {incoming} 条消息")
        print(f"传出队列:     {outgoing} 条消息")

        # 连接的节点
        connected_nodes = network_data.get("connectedNodes", [])
        if connected_nodes:
            print(f"连接节点:     {len(connected_nodes)} 个节点")
        else:
            print("连接节点:     无连接")

    def print_file_status(self):
        """打印文件状态"""
        print("\n📁 文件监控:")
        print("-" * 40)

        files_data = self.cached_data.get("files", {})

        is_running = files_data.get("isRunning", False)
        queue_size = files_data.get("eventQueueSize", 0)
        monitored_paths = files_data.get("monitoredPaths", [])

        status_text = "运行中" if is_running else "已停止"
        print(f"监控状态:     {status_text}")
        print(f"事件队列:     {queue_size} 个事件")
        print(f"监控目录:     {len(monitored_paths)} 个目录")

        # 显示监控路径
        if monitored_paths:
            print("监控路径:")
            for path in monitored_paths[:5]:  # 最多显示5个
                print(f"  📁 {path}")
            if len(monitored_paths) > 5:
                print(f"  ... 还有 {len(monitored_paths) - 5} 个")

    def print_config_info(self):
        """打印配置信息"""
        print("\n⚙️ 系统配置:")
        print("-" * 40)

        config_data = self.cached_data.get("config", {})

        # 网络配置
        network_config = config_data.get("network", {})
        print(f"网络端口:     {network_config.get('port', 'N/A')}")
        print(f"最大连接:     {network_config.get('maxConnections', 'N/A')}")
        print(f"心跳间隔:     {network_config.get('heartbeatInterval', 0)}ms")

        # 同步配置
        sync_config = config_data.get("sync", {})
        auto_enabled = "启用" if sync_config.get("autoEnabled", False) else "禁用"
        print(f"自动同步:     {auto_enabled}")
        print(f"同步间隔:     {sync_config.get('interval', 0)}ms")
        print(f"冲突策略:     {sync_config.get('conflictStrategy', 'N/A')}")

        # 日志配置
        log_config = config_data.get("log", {})
        log_enabled = "启用" if log_config.get("fileEnabled", False) else "禁用"
        print(f"日志文件:     {log_enabled}")
        print(f"日志级别:     {log_config.get('level', 'N/A')}")

    def print_footer(self):
        """打印页脚"""
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        update_time = (
            self.last_update.strftime("%H:%M:%S") if self.last_update else "从未"
        )

        # 连接状态
        if self.error_count == 0:
            connection_status = "🟢 连接正常"
        elif self.error_count < 5:
            connection_status = f"🟡 连接不稳定 ({self.error_count} 次错误)"
        else:
            connection_status = "🔴 连接断开"

        print("\n" + "=" * 80)
        print(
            f"当前时间: {current_time} | 最后更新: {update_time} | {connection_status}"
        )
        print("按 Ctrl+C 退出")
        print("=" * 80)

    def display_dashboard(self):
        """显示控制面板"""
        self.clear_screen()

        try:
            self.print_header()
            self.print_network_status()
            self.print_file_status()
            self.print_config_info()
            self.print_footer()
        except Exception as e:
            print(f"❌ 显示错误: {e}")

    @staticmethod
    def format_uptime(milliseconds: int) -> str:
        """格式化运行时间"""
        if milliseconds <= 0:
            return "未知"

        seconds = milliseconds // 1000
        if seconds < 60:
            return f"{seconds}秒"
        elif seconds < 3600:
            minutes = seconds // 60
            return f"{minutes}分钟"
        elif seconds < 86400:
            hours = seconds // 3600
            minutes = (seconds % 3600) // 60
            return f"{hours}小时{minutes}分钟"
        else:
            days = seconds // 86400
            hours = (seconds % 86400) // 3600
            return f"{days}天{hours}小时"

    def show_startup_screen(self):
        """显示启动画面"""
        self.clear_screen()
        print("=" * 60)
        print("🚀 分布式文件同步系统 简化TUI监控器")
        print("=" * 60)
        print("\n正在连接后端服务...")
        print(f"服务地址: {self.backend_url}")
        print("\n请稍候...")
        time.sleep(2)

    def show_connection_error(self):
        """显示连接错误"""
        self.clear_screen()
        print("=" * 60)
        print("❌ 连接失败")
        print("=" * 60)
        print(f"\n无法连接到后端服务: {self.backend_url}")
        print("\n请确保:")
        print("1. Java后端服务正在运行")
        print("2. API端口 8889 未被占用")
        print("3. 防火墙允许连接")
        print("\n3秒后重试...")
        time.sleep(3)

    def run(self):
        """运行TUI界面"""
        try:
            self.show_startup_screen()

            # 尝试自动认证
            print("正在尝试认证...")
            if not self.try_auto_auth():
                print("❌ 认证失败，无法连接到后端服务")
                print("请确保:")
                print("1. Java后端服务正在运行")
                print("2. 可以从日志文件获取API密钥")
                print("3. 或者admin/admin123用户可用")
                return

            # 初始测试连接
            initial_data = self.fetch_data("status")
            if not initial_data or initial_data.get("error"):
                while True:
                    self.show_connection_error()
                    # 重新尝试认证
                    if self.try_auto_auth():
                        initial_data = self.fetch_data("status")
                        if initial_data and not initial_data.get("error"):
                            break
                    initial_data = self.fetch_data("status")
                    if initial_data and not initial_data.get("error"):
                        break

            # 主循环
            while True:
                try:
                    self.update_cached_data()
                    self.display_dashboard()
                    time.sleep(3)  # 每3秒更新一次
                except KeyboardInterrupt:
                    break
                except Exception as e:
                    print(f"❌ 运行时错误: {e}")
                    time.sleep(1)

        except KeyboardInterrupt:
            pass
        finally:
            self.clear_screen()
            print("👋 感谢使用分布式文件同步系统 TUI 监控器！")


def main():
    """主函数"""
    # 简单的命令行参数解析
    import sys

    host = "localhost"
    port = 8889

    if len(sys.argv) > 1:
        host = sys.argv[1]
    if len(sys.argv) > 2:
        try:
            port = int(sys.argv[2])
        except ValueError:
            print("❌ 端口号必须是数字")
            sys.exit(1)

    print(f"启动TUI监控器...")
    print(f"后端地址: {host}:{port}")
    print()

    # 启动TUI
    tui = SimpleTUI(host, port)
    tui.run()


if __name__ == "__main__":
    main()
